# -*- coding: utf-8 -*-
import logging, urllib, re, os
from app.gmemsess import Session
from src import bucketsCache, clearCache, idAndKey, aclCache, browserCheck, boto, json, config
from src.Base import Base, History


class MainHandler(Base):
	def get(self):
		self.redirect('/storage/')
		#self.render('index.html', None)



class Storage(Base):
	''' google storage customize '''

	@browserCheck
	def get(self, slug='/'):
		if not slug:
			self.redirect('/storage/')
			return

		session = Session(self)

		id = session.get('gsId')
		key = session.get('gsKey')
		buckets = {}
		slug = unicode(urllib.unquote(slug[1:]), 'utf-8')

		if id and key:
			buckets = self.getBuckets(slug)
			if buckets is not None:
				History.get_or_insert(id, id_=id, key_=key, ip=self.request.remote_addr)
		else:
			self.errorMsg = '输入ID和Key试用'
			id = ''

		if not slug:
			self.render('storage.html', {'gs': {'buckets': buckets, 'id': id, 'errorMsg': self.errorMsg}})
		else:
			import types
			self.write((buckets) if type(buckets) ==  types.StringType else json.write(buckets))#json.write()

	def post(self, slug=None):
		slug = slug[1:]
		if hasattr(self, slug):
			getattr(self, slug)()
		else:
			self.error(404)

	@Base.doPost
	def login(self):
		session = Session(self)
		session['gsId'] = self.param('id').strip()
		session['gsKey'] = self.param('key').strip()
		session.save()
		#self.response.headers.add_header('Set-Cookie','id=%s; Path=/' % self.param('id'))
		self.redirect('/storage/')

	@Base.doPost
	def newBucket(self):
		try:
			path = self.param('path')
			name = self.param('name')
			uri_bucket = boto.storage_uri(path if path else name, "gs")
			if not path:
				uri_bucket.create_bucket()
			else:
				uri_bucket.clone_replace_name((self.getPrefix(path) + name + '_$folder$')).new_key().set_contents_from_string('')
			self.write(u'^1创建成功: ' + self.param('name'))
		except boto.exception.BotoServerError, e:
			self.write(u'^0创建失败: ' + self.param('name') + ", " + e.error_message)
		except Exception, e:
			self.write(u'^0创建失败: ' + self.param('name') + ", " + e.message)


	@Base.doPost
	def getAcl(self):
		path = urllib.unquote(self.param('path'))
		try:
			keyAcls = self.keyAcl(path, self.request.get_all('keys[]'))
			#keys = bucket.get_all_keys(prefix='/'.join(path.split('/')[1:]), marker=lastTd, max_keys=maxPos)
			#keyAcls = {'\xe4\xb8\xad\xe6\x96\x87/acl.txt': True, 'Link to index.html': False, '查 落水狗.txt': True, 'a\'/b\"/a\"b.xml': True}
			self.write(json.write(keyAcls))
		except Exception:
			self.errorMsg = 'get acl error.'
			self.error(500)


	@idAndKey
	@aclCache
	def keyAcl(self, path, keys, **kwargs):
		bucket = boto.storage_uri(path, 'gs').get_bucket()
		keyAcls = {}
		for key in keys:
			keyAcls[key] = self.isPublic(bucket.get_key(key.encode('utf-8')))
		return keyAcls

	@Base.doPost
	def history(self):
		rs = [h.toString() for h in History.all()]
		self.write(rs)

	@Base.doPost
	def deleteBucket(self):
		try:
			#uri_bucket = boto.storage_uri(self.param('name'), "gs")
			#uri_bucket.delete_bucket()
			self.write(u'^1删除成功: ' + self.param('name'))
		except boto.exception.BotoServerError, e:
			self.write(u'^0删除失败: ' + self.param('name') + ", " + e.error_message)
		except Exception, e:
			self.write(u'^0删除失败: ' + self.param('name') + ", " + e.message)

	@idAndKey
	@Base.doPost
	def makePublic(self, **kwargs):
		name = urllib.unquote(self.param('name').encode('utf-8'))

		key = boto.storage_uri(name, 'gs').get_key() #'twty1988/photo/5/FILE1312.JPG'
		isPrivate = not self.isPublic(key)
		key.make_public() if isPrivate else key.set_canned_acl('private')
		self.write('^1' + str(isPrivate))

	#return

	#@idAndKey
	#@Base.doPost
	def upload(self, **kwargs):
		import tempfile, time

		name = self.request.headers['UP-FILENAME']
		path = self.request.headers['UP-GS-PATH']
		logging.info('upload '+ path + '/' + name)
		
		#file.write(self.param('file'))

		uri_bucket = boto.storage_uri(path, "gs")
		uri_bucket.clone_replace_name(self.getPrefix(path) + name).new_key().set_contents_from_file(self.request.body_file)
		'''
		time.sleep(2)
		f = open('upload/' + name, 'w+b')

		f.write(self.request.body_file.read())
		f.close()'''
		self.write(name)

	def getNewName(path, keys):
		pass

	def moveKey(self, key, newBucket, newName):
		key.copy(newBucket, newName)
		key.delete()

	@idAndKey
	@Base.doPost
	def rename(self, **kwargs):
		path = self.param('path')
		key = self.param('key').encode('utf-8')
		newName = self.param('name').encode('utf-8')
		if key.endswith(self.emptyFolder):
			key = key[:-len(self.emptyFolder)]
			prefix = self.getPrefix(key)
			newKey = key.split('/')[1:]
			newKey[-1] = newName
			newKey = '/'.join(newKey) + '/'
			logging.info(newKey)

			reg = re.compile('^' + prefix)
			
			keys = boto.storage_uri(path, 'gs').get_bucket().list(prefix)
			logging.info('rename folder ' + key  + " => " + newName)
			for k in keys:
				self.moveKey(k, k.bucket.name, reg.sub(newKey, k.name))
				logging.info(k.name + " => " + reg.sub(newKey, k.name))

			self.clearBucket(path)
			self.clearBucket(unicode(key,'utf-8'))
			self.clearBucket(os.path.join(path, newName))
		else:
			newName = self.getPrefix(os.path.split(key)[0]) + newName
			key = boto.storage_uri(key, 'gs').get_key()
			self.moveKey(key, key.bucket.name, newName)
			logging.info('rename ' + key.name)

		self.write('^1ok')

	def copyKey(self, **kwargs):
		path = self.param('path')
		keys = self.request.get_all('keys[]')
		newName = self.param('name')
		type = kwargs.get('type')
		if not newName.endswith('/'):
			newName += '/'
		
		for key in keys:
			if key.endswith(self.emptyFolder):
				key = key[:-len(self.emptyFolder)]
				prefix = self.getPrefix(key)
				subKeys = boto.storage_uri(path, 'gs').get_bucket().list(prefix)
				reg = re.compile('^' + self.getPrefix(path))
				for subKey in subKeys:
					name =  '/'.join(reg.sub(newName, unicode(subKey.name,'utf-8')).encode('utf-8').split('/')[1:])
					if type != 'delete':
						subKey.copy(newName.split('/')[0].encode('utf-8'), name)
					if type in ['move', 'delete']:
						subKey.delete()
					logging.info(type + '>>> ' + name)
			else:
				name = '/'.join((newName + os.path.split(key)[-1]).split('/')[1:])
				key = boto.storage_uri(key.encode('utf-8'), 'gs').get_key()
				if type != 'delete':
					key.copy(newName.split('/')[0].encode('utf-8'), name.encode('utf-8'))
				if type in ['move', 'delete']:
					key.delete()
				logging.info(type + '>' + name)

		self.clearBucket(self.param('name'))
		if type != 'copy':
			self.clearBucket(path)

		self.write('^1ok')			

	@idAndKey
	@Base.doPost
	def copy(self, **kwargs):
		kwargs['type'] = 'copy'
		self.copyKey(**kwargs)

	@idAndKey
	@Base.doPost
	def move(self, **kwargs):
		kwargs['type'] = 'move'
		self.copyKey(**kwargs)

	@idAndKey
	@Base.doPost
	def delete(self, **kwargs):
		kwargs['type'] = 'delete'
		self.copyKey(**kwargs)
		
	@idAndKey
	@bucketsCache
	def getBuckets(self, path, **kwargs):
		try:
			uri = boto.storage_uri(path, 'gs')
			if path:
				keys = uri.get_bucket().list(self.getPrefix(path))
				return [[obj.name.decode('utf-8'), obj.size, obj.last_modified] for obj in keys]
			return  [bucket.name for bucket in uri.get_all_buckets()]
		except boto.exception.BotoServerError, e:
			self.errorMsg = e.error_message
			logging.error(e)
			self.error(404)
			return None
		except Exception, e:
			self.errorMsg = e.message
			logging.error(e)
			self.error(404)
			return None

	@Base.doPost
	@clearCache
	def clearBucket(self, *args, **kwargs):
		path = args[0] if args else self.param('path')
		retrieve = self.param('retrieve') == 'true'
		if retrieve:
			self.write(json.write(self.getBuckets(path)))


	def getPrefix(self, path):
		prefix = path.split('/')
		prefix = '/'.join(prefix[1:])
		if prefix: prefix += '/'
		return prefix

	def isPublic(self, key):
		acls = key.get_acl().entries.entry_list
		for acl in acls:
			if acl.scope.type == boto.gs.acl.ALL_USERS and acl.permission == boto.gs.acl.SupportedPermissions[0]:
				return True
		return False
